package cn.edu.besti.is.onlinecalculator;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import java.io.*;
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import java.net.*;

public class Client {
    public static String Connect(String formula, String mod) throws Exception {
        String mode = "AES";
        Socket mysocket;
        DataInputStream in;
        DataOutputStream out;
        mysocket = new Socket();
        mysocket.connect(new InetSocketAddress("172.30.7.19", 2010),5000);
        mysocket.setSoTimeout(5000);
        in = new DataInputStream(mysocket.getInputStream());
        out = new DataOutputStream(mysocket.getOutputStream());
        //使用AES进行后缀表达式的加密
        KeyGenerator kg = KeyGenerator.getInstance(mode);
        kg.init(128);
        SecretKey k = kg.generateKey();//生成密钥
        byte[] mkey = k.getEncoded();
        Cipher cp = Cipher.getInstance(mode);
        cp.init(Cipher.ENCRYPT_MODE, k);
        byte[] ptext = formula.getBytes("UTF8");
        byte[] ctext = cp.doFinal(ptext);

        //将加密后的后缀表达式传送给服务器
        String out1 = B_H.parseByte2HexStr(ctext);
        out.writeUTF(out1);

        //创建客户端DH算法公、私钥
        KeyPair keyPair = Key_DH5_6.createPubAndPriKey();
        PublicKey pbk = keyPair.getPublic();//Client公钥
        PrivateKey prk = keyPair.getPrivate();//Client私钥

        //将公钥传给服务器
        byte[] cpbk = pbk.getEncoded();
        String CpubKey = B_H.parseByte2HexStr(cpbk);
        out.writeUTF(CpubKey);
        Thread.sleep(1000);

        //接收服务器公钥
        String SpubKey = in.readUTF();
        byte[] spbk = H_B.parseHexStr2Byte(SpubKey);
        KeyFactory kf = KeyFactory.getInstance("DH");
        PublicKey serverPub = kf.generatePublic(new X509EncodedKeySpec(spbk));

        //生成共享信息，并生成AES密钥
        SecretKeySpec key = KeyAgree5_6.createKey(serverPub, prk);

        //对加密后缀表达式的密钥进行加密，并传给服务器
        cp.init(Cipher.ENCRYPT_MODE, key);
        byte[] ckey = cp.doFinal(mkey);
        String Key = B_H.parseByte2HexStr(ckey);
        out.writeUTF(Key);

        out.writeUTF(mod);
        //接收服务器回答
        return in.readUTF();
    }
}

